package com.egghiro.framework.j2se.game.utils;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.InvalidPropertiesFormatException;
import java.util.List;
import java.util.MissingResourceException;
import java.util.Properties;
import java.util.ResourceBundle;

import com.egghiro.framework.j2se.game.core.consts.SGConst;

public class PropertyUtils {

    // 內存常駐Properties
    private static HashMap<String, Properties> alwaysInMemoryPropertiesMap = null;

    private static final byte[] lock = new byte[0];

    private PropertyUtils() {

    }

    /**
     * プロパティファイルから設定値を取得する
     * 
     * @param fileName
     *            プロパティファイル名
     * @param key
     *            キー
     * @return 設定値
     * @throws MissingResourceException
     */
    public static String getPropertyValue(String fileName, String key) throws MissingResourceException {
        // String propFileName = fileName.replaceAll(SGConst.PROPERTIES_EXTENSION, "");
        //
        // ResourceBundle bundle = ResourceBundle.getBundle(propFileName);
        //
        // String rtnValue = bundle.getString(key);
        //
        // return rtnValue;
        return getProperties(fileName).getProperty(key);
    }

    /**
     * プロパティファイルから設定値を取得する
     * 
     * @param fileName
     *            プロパティファイル名
     * @param key
     *            キー
     * @param DEFAULT_VALUE
     *            プロパティファイルがない、またはキー値がないときにリターンするデフォルトの値
     * @return 設定値
     */
    public static String getPropertyValue(String fileName, String key, final String DEFAULT_VALUE) {
        // String propFileName = fileName.replaceAll(SGConst.PROPERTIES_EXTENSION, "");
        //
        // ResourceBundle bundle = ResourceBundle.getBundle(propFileName);
        //
        // String rtnValue = bundle.getString(key);
        //
        // return rtnValue;
        String value = null;
        try {
            value = getPropertyValue(fileName, key);
        } catch (MissingResourceException e) {
            value = null;
        }

        if (value == null) {
            value = DEFAULT_VALUE;
        }

        return value;

    }

    /**
     * 
     * @param propertyFileList
     * @param key
     * @return
     */
    public static String getPropertyValue(List<String> propertyFileList, String key) {
        String value = null;
        for (String propertyFile : propertyFileList) {
            value = getPropertyValue(propertyFile, key, null);
            if (value != null) {
                break;
            }
        }

        return value;
    }

    /**
     * 
     * @param propertyFileList
     * @param key
     * @return
     */
    public static String getPropertyValue(String[] propertyFileArray, String key) {
        return getPropertyValue(Arrays.asList(propertyFileArray), key);
    }

    /**
     * 指定したプロパティファイル名によりプロパティファイルを取得する
     * 
     * @param fileName
     *            プロパティファイル名
     * @return プロパティファイル
     * 
     * @throws MissingResourceException
     */
    private static Properties getProperties(String fileName) throws MissingResourceException {
        Properties props = new Properties();

        ResourceBundle bundle = ResourceBundle.getBundle(fileName.replaceAll(SGConst.PROPERTIES_EXTENSION, ""));

        Enumeration<String> keys = bundle.getKeys();

        while (keys.hasMoreElements()) {
            String key = keys.nextElement();
            props.setProperty(key, bundle.getString(key));
        }

        return props;
    }

    /**
     * 【未完成】パスに関して試してみる。今まだ必要ではないため完成していない。 XMLファイルからPropertiesを読み込む XMLファイルに文字コードを設定すれば漢字も可
     * 
     * @param fileName
     * @return 取得したプロパティ。エラーが発生し取得できなかった場合、nullをreturn
     */
    private static Properties getPropertiesFromXML(String fileName) {
        Properties properties = null;
        FileInputStream xmlFile = null;

        try {
            properties = new Properties();

            // TODO フルパスでないとだめ？
            String filePath = fileName;

            xmlFile = new FileInputStream(filePath);

            properties.loadFromXML(xmlFile);
        } catch (FileNotFoundException e) {
            // TODO
        } catch (InvalidPropertiesFormatException e) {
            // TODO
        } catch (IOException e) {
            // TODO
        } finally {
            // ファイルクローズを行う
            if (xmlFile != null) {
                try {
                    xmlFile.close();
                } catch (IOException e) {
                    // TODO
                }
            }
        }

        return properties;
    }

    /**
     * 取得常駐Property
     * 
     * @return
     */
    private static Properties getAIMProperties(String propertiesFileName) {
        if (alwaysInMemoryPropertiesMap == null) {
            synchronized (lock) {
                if (alwaysInMemoryPropertiesMap == null) {
                    alwaysInMemoryPropertiesMap = new HashMap<String, Properties>();

                    String aimFilesString = getSystemPropertyValue(SGConst.PROPERTIES_KEY_AIMPS);

                    try {
                        for (String aimFile : aimFilesString.split(SGConst.PROPERTY_SEPARATOR)) {
                            try {
                                alwaysInMemoryPropertiesMap.put(aimFile, getProperties(aimFile));
                            } catch (MissingResourceException e) {
                                // TODO ?ログ?
                                e.printStackTrace();
                            }
                        }
                    } catch (NullPointerException e) {
                        // TODO ?ログ?
                        e.printStackTrace();
                    }
                }
            }
        }

        Properties aimProperties = alwaysInMemoryPropertiesMap.get(propertiesFileName);
        if (aimProperties == null) {
            // TODO getPropertiesFromXML
            aimProperties = getProperties(propertiesFileName);
            alwaysInMemoryPropertiesMap.put(propertiesFileName, aimProperties);
        }

        return aimProperties;
    }

    /**
     * 取得內存常駐Property的Value
     * 
     * @param propertiesFileName
     * @param key
     * @return 內存常駐Property的Value
     */
    public static String getAIMPropertyValue(String propertiesFileName, String key) {
        return getAIMProperties(propertiesFileName).getProperty(key);
    }

    /**
     * ※システムプロパティはデフォルトメモリ常駐しない
     * 
     * @param key
     * @return
     */
    public static String getSystemPropertyValue(String key) {
        // String value = getPropertyValue(SGConst.SYSTEM_PROPERTIES_FILE, key, null);
        //
        // if (value == null) {
        // value = getPropertyValue(SGConst.DEFAULT_SYSTEM_PROPERTIES_FILE, key);
        // }
        //
        // return value;
        return getPropertyValue(
                new String[] { SGConst.SYSTEM_PROPERTIES_FILE, SGConst.DEFAULT_SYSTEM_PROPERTIES_FILE }, key);
    }

    //
    // public static String getSystemPropertyValue(String key, final String DEFAULT_VALUE){
    //
    // String value = null;
    // try {
    // value = getSystemPropertyValue(key);
    // } catch (MissingResourceException e) {
    // value = null;
    // }
    //
    // if (value == null) {
    // value = DEFAULT_VALUE;
    // }
    //
    // return value;
    //
    // }
    //
    // private static Properties getSystemProperties(){
    // Properties systemProperties = null;
    // try{
    // systemProperties = getProperties(SGConst.SYSTEM_PROPERTIES_FILE);
    // } catch (MissingResourceException e){
    // systemProperties = getProperties(SGConst.DEFAULT_SYSTEM_PROPERTIES_FILE);
    // }
    //
    // return systemProperties;
    // }

    //
    // /**
    // * プロパティファイルの値を取得する.
    // * 指定したキーに対応する値をプロパティファイルから取得する.
    // *
    // * @param propsName リソース名
    // * @param key キー
    // * @param flg true = 通常の形式のプロパティファイル false = ＸＭＬ形式のプロパティファイル
    // * @return キーに対応する値
    // * @throws IOException
    // * @throws InstantiationException
    // * @throws IllegalAccessException
    // * @exception NullPointerException キーがnullである場合
    // * @exception MissingResourceException 指定された基底名のリソースバンドルが見つからない場合
    // */
    // private static String get(String propsName,String key,Boolean flg)
    // throws IOException, IllegalAccessException, InstantiationException {
    //
    // ResourceBundle resourceBundle;
    // ACOM_xmlResourceBundleControl xmlResourceBundleControl = new ACOM_xmlResourceBundleControl();
    //
    // if (flg == true){
    //
    // if(propsMap.containsKey(propsName) == false){
    //
    // resourceBundle = ResourceBundle.getBundle(propsName);
    // propsMap.put(propsName, resourceBundle);
    //
    // }
    // } else {
    //
    // if(propsMap.containsKey(propsName) == false){
    //
    // resourceBundle = xmlResourceBundleControl.getBundle(propsName);
    // propsMap.put(propsName, resourceBundle);
    //
    // }
    //
    // }
    // return ACOM_envUtil.changeEnv( propsMap.get(propsName).getString(key));
    // }
    //
    // public static String getProps(String propsName,String key)
    // throws IOException, IllegalAccessException, InstantiationException {
    // return get(propsName , key, true);
    // }
    //
    // public static String getXml(String propsName,String key)
    // throws IOException, IllegalAccessException, InstantiationException {
    // return get(propsName ,key ,false);
    // }
}
